<template>
  <div>
    <div class="select" v-if="choices.length > 0">
      <div>已选：</div>
      <div v-if="item.label" v-for="item in choices" :key="item.key">
        <Tag size="large" closable @on-close="onClose(item.key)">
          <span v-if="item.title != ''">{{ item.title }}:</span>
          {{ item.label }}
        </Tag>
      </div>
      <Button type="primary" class="reset" @click="onReset">重置</Button>
    </div>

    <div
      v-if="option"
      class="content"
      @mouseover="onMouseover"
      @mouseleave="onMouseleave"
      :style="{
        left: left + 'px',
        top: top + 'px',
        width: width + 'px'
      }">
      <!--  尖头   -->
      <div class="arrow" :style="{ left: iconLeft - left + 'px' }">
        <span></span>
      </div>

      <div class="input" v-if="option">
        <edit :option="option" :info="tmpInfo" @change="onChange"></edit>
      </div>

      <!-- 底部 -->
      <div class="foot">
        <Button type="primary" @click="onOK">确定</Button>
        <Button type="default" @click="onCancel">取消</Button>
      </div>
    </div>
  </div>
</template>
<script>
  import edit from '../info/dt-info-edit.vue'
  import dt from '@dt/dt'
  let timeout = null

  class Filter {
    constructor() {
      this.conditions = {} // info label option choice
    }
    initOpt(option) {
      // 初始化
      if (!this.conditions[option.key]) {
        this.conditions[option.key] = { option, info: {} }
      }
    }
    updateOpts(options) {
      // 初始化
      Object.keys(this.conditions).forEach((key) => {
        if (!options?.some((opt) => opt.key == key)) {
          this.conditions[key].choice = false
          this.conditions[key].info = {}
          this.conditions[key].label = null
        }
      })
    }
    info(key) {
      // 取当前值
      return this.conditions[key].info
    }
    isChoice(key) {
      return this.conditions[key].choice
    }
    choice(key, val = true) {
      // 选择
      this.conditions[key].choice = val && this.conditions[key].label
      if (!val) {
        this.conditions[key].info = {}
      }
    }
    clear() {
      // 清空
      Object.keys(this.conditions).forEach((key) => {
        this.conditions[key].choice = false
        this.conditions[key].info = {}
        this.conditions[key].label = null
      })
    }
    value(opt, val) {
      // 赋值
      let key = opt.key
      let label = val
      if (opt.date) {
        if (Array.isArray(val)) {
          label =
            val[0].length > 0
              ? `${val[0].replace(' 00:00:00', '')} ~ ${val[1].replace(' 23:59:59', '')}`
              : null
        } else {
          label = val.length > 0 ? val : null
        }
      } else if (opt.select || opt.cascader) {
        if (Array.isArray(val)) {
          label = ''
          val.forEach((v, i) => {
            label +=
              v.label ?? (opt.select?.key
                ? dt.dictInfo().__value(opt.select.key, v)
                : opt.select?.options.filter((ele) => (ele.key == v))[0]?.value)
            if (i != val.length - 1) {
              label += ','
            }
          })
        } else {
          label =
            val.label ?? (opt.select?.key
              ? dt.dictInfo().__value(opt.select.key, val)
              : opt.select?.options.filter((ele) => (ele.key == val))[0]?.value)
        }
      } else if (opt.dtTime) {
        console.log(val)
        if (Array.isArray(val)) {
          label = val.join(' ~ ')
        } else {
          label = val.label
        }
      }
      this.conditions[key].label = label
    }
    update() {
      let choices = []
      let infos = {}
      Object.keys(this.conditions).forEach((key) => {
        let item = this.conditions[key]
        if (item.choice) {
          infos = { ...infos, ...item.info }
          choices.push({
            title: item.option.title,
            label: item.label,
            key
          })
        }
      })
      return {
        choices,
        infos
      }
    }
  }

  export default {
    components: {
      edit
    },
    props: {
      value: Object,
      items: Array
    },
    data() {
      return {
        option: null,
        tmpInfo: {},

        filter: new Filter(),
        choices: [],
        infos: {},

        left: 0,
        top: 0,
        width: 230,
        iconLeft: 0
      }
    },
    methods: {
      init() {
        this.filter.updateOpts(this.items)
        this.items.forEach((opt) => {
          let key = opt.key
          let from = opt.data ? opt.data.from : null
          let to = opt.data ? opt.data.to : null
          let value = from ? from(this.value) : this.value[key]
          let obj = {}
          if (value) {
            // 只支持原始数据，即转化过的数据不兼容
            if (to) {
              obj = to(value)
            } else {
              obj[key] = value
            }
            this.filter.initOpt(opt)
            if (!this.filter.isChoice(key)) {
              this.filter.value(opt, value)
              this.filter.choice(key)
            }
            Object.assign(this.filter.info(key), obj)
          }
        })
        this.update()
      },
      export() {
        // 导出
        return this.filter
      },
      import(filter) {
        // 导入
        if (filter) {
          this.filter = filter
          this.filter.updateOpts(this.items)
          this.update()
        }
      },
      clear() {
        this.filter.clear()
        this.update()
      },
      onMouseover(e, opt) {
        e.stopPropagation()
        clearTimeout(timeout)
        if (opt) {
          this.width = opt.width ?? 230
          let width = this.width / 2 - 5
          let rect = e.currentTarget.getBoundingClientRect()
          let left = rect.left - width
          let clientWidth = document.documentElement.clientWidth
          this.left = Math.max(200, left + this.width > clientWidth ? clientWidth - this.width : left)
          this.top = rect.top + 20
          this.iconLeft = rect.left

          if (opt.input) {
            opt.input.prefix = 'ios-search'
          } else if (opt.select) {
            opt.select.transfer = false
          }

          this.option = opt
          this.filter.initOpt(opt)
          this.tmpInfo = this.filter.info(opt.key)

          console.info('dt-filter: 已选值', this.tmpInfo)
        }
      },
      onMouseleave(e) {
        e.stopPropagation()
        let time = this.tmpInfo[this.option.key]?1000:500
        timeout = setTimeout(() => {
          this.option = null
        }, time)
      },
      onClose(key) {
        this.filter.choice(key, false)
        this.search()
      },
      onReset() {
        this.clear()
        this.search(true)
      },
      // 确定
      onOK() {
        if (
          !this.option.filter ||
          !this.option.filter.check ||
          this.option.filter.check(this.filter.info(this.option.key))
        ) {
          this.filter.choice(this.option.key)
          this.search()
          this.option = null
        }
      },
      update() {
        let res = this.filter.update()
        this.infos = res.infos
        this.choices = res.choices
        this.$emit('input', this.infos)
      },
      search(reset = false) {
        this.update()
        this.$emit('filter', this.infos, reset)
      },
      // 取消
      onCancel() {
        this.option = null
      },
      onChange(data) {
        this.filter.value(this.option, data.editValue)
      }
    },
    mounted() {
      this.$parent.$$filter = this
    }
  }
</script>
<style lang="scss" scoped>
  .select {
    display: flex;
    align-items: center;
    line-height: 35px;
    flex-wrap: wrap;

    > * {
      // margin-bottom: 10px;
    }
  }

  .content {
    z-index: 101;
    background-color: #fff;
    box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.1);
    position: fixed;
  }

  .input {
    padding: 14px;
  }

  .table_filter_checkbox {
    padding: 14px 14px 11px 14px;
  }

  .foot {
    border-top: 1px solid #dcdee2;
    text-align: center;
    padding: 14px 0;

    button {
      margin: 0 10px;
    }
  }

  .arrow {
    position: absolute;
    top: -6px;
    margin-left: 2px;

    span:after {
      display: block;
      content: ' ';
      width: 0;
      height: 0;
      border-right: 6px solid transparent;
      border-left: 6px solid transparent;
      border-bottom: 6px solid #fff;
    }
  }
</style>
